In computer systems, the memory available for use by the processor is a limited resource. Because of this limitation, instead of loading into memory every page of data required for a given program to run, pages are loaded as required. The program's “view” of memory is a logical view, in which all pages may be referenced. However, the main memory does not contain all these pages. Instead, some pages may be stored in a secondary storage, which is used to supplement the main memory. When a program requires a page which is not in the main memory, it is brought in from the secondary storage for use by the program.
When the space that page uses in main memory is needed, if the page has been changed, the changed page is written (“swapped”) out to the secondary storage and the space is again available. If the page has not been changed, its physical space is just marked as available space. Generally, the translation from virtual memory space to physical memory and the loading and swapping of pages into physical memory is transparent to the program. In some cases, the program may have some knowledge of the virtual memory system in order to allow it to optimize performance.
Numerous techniques exist for loading pages into main memory, including techniques which anticipate and pre-load pages which may be used, and for swapping pages out to the secondary storage. As described, data may be stored in pages of a fixed size. Other virtual memory techniques exist, in which variable sizes of data may be allowed to be brought in and swapped out of main memory.
In some cases, when code (e.g. a binary) is loaded for use, the code page is modified. There are several common reasons why a code page is modified. For example, when code is loaded into a process with a base address different than the original base address of the code, the code needs to be adjusted (“rebased”) to reflect the new base address throughout the code. By performing such rebasing, the code will function correctly in its new location, and references throughout the code to the base address or to addresses based on the base address will be correct. Some code contains a presumptive base memory address, and can run with no modifications if it is loaded into that base memory address in virtual memory. Rebasing will be necessary when the code cannot be loaded into virtual memory starting at that presumptive base memory address. Each new load location into virtual memory requires rebasing, which is processor-time intensive. Storing each new instance of the code in virtual memory also takes up virtual memory.
As described above, virtual memory techniques were created because memory is a limited resource in a computer. However, virtual memory is also in some sense a limited resource in a computer. This is because, where a number of processes are running and requiring that many pages be swapped (or where a single process requires accesses to many locations scattered among different pages, thus also requiring that many pages be swapped), then the system “thrashes.” When thrashing occurs, too much of the activity of the computer system is concerned with swapping pages into and out of main memory. System performance is degraded.
While virtual memory aids with problems resulting from the limited amount of main memory, the secondary memory is also limited. This limitation is also significant—if a system requires a great deal of secondary memory, then access times for the secondary memory may be increased, and generally, costs for the system may be significant.
The problem of virtual memory thrashing and limitations of secondary memory are magnified in a time sharing environment where there are many users running processes on the same machine.